#define _GNU_SOURCE
// #define _XOPEN_SOURCE 500
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>

pid_t pty_fork()
{
    int fdm, fds;
    char *name; // slave pty name
    pid_t pid;

    fdm = open("/dev/ptmx", O_RDWR);
    if (fdm < 0) {
        printf("open master pty error\n");
        goto master_error;
    }

    if (grantpt(fdm) < 0 || unlockpt(fdm) < 0) {
        printf("access master pty error\n");
        goto master_error;
    }

    name = ptsname(fdm);
    if (name == NULL) {
        printf("get slave pty name error!\n");
        goto master_error;
    }

    /* slave */
    fds = open(name, O_RDWR);
    if (fds < 0) {
        goto slave_error;
    }

    pid = fork();
    if (pid < 0) {
        return -1;
    } else if (pid == 0) { // child
        if (setsid() < 0) {
            return -1;
        } 
        close(fdm);
        ioctl(fds, TIOCSCTTY, 0);
#if 1
        if (dup2(fds, STDIN_FILENO) != STDIN_FILENO) {
            return -1;
        }
        if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) {
            return -1;
        }
        if (dup2(fds, STDERR_FILENO) != STDERR_FILENO) {
            return -1;
        }
        if (fds != STDIN_FILENO && fds != STDOUT_FILENO && fds != STDERR_FILENO) {
            return -1;
        }
#endif
        char *argv[] = {"login", NULL};
        execvp(argv[0], argv);
        printf("maybe\n");
    } else { // parent
        return pid;
    }

master_error:
    close(fdm);
    return -1;

slave_error:
    return -2;
}

int main()
{
    char buf[512];
    int mfd = pty_fork();

    printf("--\n");
    sleep(5);
}
